perm filename DETECT.PAL[HAL,HE] blob
sn#173886 filedate 1975-08-15 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00011 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 Data structures
C00003 00003 NNSEARCH
C00008 00004 BOB, BWB
C00011 00005 DISTANCE, DISLOOP, QUERY
C00015 00006 MAKETREE
C00022 00007 GETSPREAD
C00025 00008 GETDVAL
C00030 00009 NWSORT, RLSORT, NWBOUNDS, NWHUNK, NWNODE
C00032 00010 Test
C00036 00011 Known bugs
C00037 ENDMK
C⊗;
; Data structures
;Tree node
II == 0
XX TVAL ;The value
XX DISCRIM ;Discriminating direction (if -1, the left
; son is the bucket of hunks.)
XX TLEFT ;Left son
XX TRIGHT ;Right son
NODESZ == II/2
;Hunk
II == 0
XX HLOW ;Array of 3 low values
XX HLOW2
XX HLOW3
XX HHIGH ;Array of 3 high values
XX HHIGH2
XX HHIGH3
XX HNEXT ;For linked buckets
HUNKSZ == II/2
;Sort cell
II == 0
XX SCVAL ;The value
XX SCNEXT ;The next one
SCSIZ == II/2
SOUGHT: .BLKW 3 ;The point being sought
NEAREST: 0 ;The nearest so far found.
; NNSEARCH
COMMENT ⊗ Does a nearest neighbor search in NNTREE restricted by
bounds arrays NNLOWS and NNHIGHS to see how close the point at SOUGHT
(a global location) is to any hunk in the tree. This is a recursive
procedure, and at each call returns R0 = 0 if it is worth continuing
the search (based on Bounds-Within-Ball tests). ⊗
ROUTINE NNSEARCH,<NNTREE,NNLOWS,NNHIGHS>
TST NNTREE(RF) ;Tree null?
BNE NNS1 ;No
NNS3: CLR R0 ;But ought to continue.
RTS RF ;Done
NNS1: MOV R2,-(SP) ;Save R2
MOV NNTREE(RF),R2 ;R2 ← Tree
TST DISCRIM(R2) ;DISCRIM = -1?
BGE NNS2 ;No
CALL QUERY,<TLEFT(R2)> ;Yes. At base of tree. Query.
CALL BWB,<NNLOWS(RF),NNHIGHS(RF)> ;See if worth continuing.
MOV (SP)+,R2 ;Restore R2
TST R0 ;So caller won't have to.
RTS RF ;And return
NNS2:
MOV #3,R0 ;Make a NEWS array
JSR PC,GTFREE ;
MOV R0,-(SP) ;Save LOC[NEWS]
MOV DISCRIM(R2),R1 ;
CMP SOUGHT(R1),TVAL(R2) ;Which side?
BGT NNS6 ;
;left side first
MOV NNHIGHS(RF),R1 ;NEWS ← NNHIGHS
MOV (R1)+,(R0)+ ;
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV (SP),R0 ;
ADD DISCRIM(R2),R0 ;NEWS[DISCRIM] ← TVAL
MOV TVAL(R2),(R0) ;
MOV (SP),R0 ;
CALL NNSEARCH,<TLEFT(R2),NNLOWS(RF),R0>
BNE NNFAIL ;Don't continue if NNSEARCH failed.
MOV (SP),R0 ;NEWS ← NNLOWS
MOV NNLOWS(RF),R1 ;
MOV (R1)+,(R0)+ ;
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV (SP),R0 ;
ADD DISCRIM(R2),R0 ;NEWS[DISCRIM] ← TVAL
MOV TVAL(R2),(R0) ;
MOV (SP),R0 ;
CALL BOB,<R0,NNHIGHS(RF)> ;
BNE NNS5 ;Don't look at other side if BOB fails.
MOV (SP),R0 ;
CALL NNSEARCH,<TRIGHT(R2),R0,NNHIGHS(RF)>
BNE NNFAIL ;Don't continue if NNSEARCH failed
NNS5: CALL BWB,<NNLOWS(RF),NNHIGHS(RF)>
BNE NNFAIL ;Don't continue if BWB failed
NNSUC: MOV (SP)+,R0 ;Release the NEWS array
JSR PC,RLFREE ;
MOV (SP)+,R2 ;Restore R2
CLR R0 ;We succeed -- need to continue
RTS RF ;Return
NNFAIL: MOV (SP)+,R0 ;Release the NEWS array
JSR PC,RLFREE ;
MOV (SP)+,R2 ;Restore R2
MOV #-1,R0 ;We fail -- no need to continue
RTS RF ;Return
;right side first
NNS6: MOV NNLOWS(RF),R1 ;NEWS ← LOWS
MOV (R1)+,(R0)+ ;
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV (SP),R0 ;
ADD DISCRIM(R2),R0 ;NEWS[DISCRIM] ← TVAL
MOV TVAL(R2),(R0) ;
MOV (SP),R0 ;
CALL NNSEARCH,<TRIGHT(R2),R0,NNHIGHS(RF)>
BNE NNFAIL ;Don't continue if NNSEARCH failed,
MOV (SP),R0 ;NEWS ← NNHIGHS
MOV NNHIGHS(RF),R1 ;
MOV (R1)+,(R0)+ ;
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV (SP),R0 ;
ADD DISCRIM(R2),R0 ;NEWS[DISCRIM] ← TVAL
MOV TVAL(R2),(R0) ;
MOV (SP),R0 ;
CALL BOB,<NNLOWS(RF),R0> ;
BNE NNFAIL ;Don't look at other side if BOB fails.
MOV (SP),R0 ;
CALL NNSEARCH,<TLEFT(R2),NNLOWS(RF),R0>
BNE NNFAIL ;Terminate as in the other case
BR NNS5 ;
; BOB, BWB
ROUTINE BOB,<BBLOWS,BBHIGHS>
COMMENT ⊗ Returns in R0 tested 0 iff worth continuing,
that is, the bounds do overlap the ball. ⊗
MOV R2,-(SP) ;Save R2
MOV R3,-(SP) ;Save R3
MOV BBLOWS(RF),R2 ;R2 ← LOC[BBLOWS];
MOV BBHIGHS(RF),R3 ;R3 ← LOC[BBHIGHS]
JSR PC,DISLOOP ;
MOV (SP)+,R3 ;Restore R3
MOV (SP)+,R2 ;Restore R2
CMP R0,NEAREST ;Overlap?
BGT BOB1 ;No.
CLR R0 ;Yes.
BOB1: RTS RF ;
ROUTINE BWB,<BWLOWS,BWHIGHS>
COMMENT ⊗ Ball-within-bounds test. Returns R0 = 0 iff it is worth
continuing, that is, the current NEAREST radius about SOUGHT does not
fall completely within the given bounds. ⊗
MOV R2,-(SP) ;Save R2
CLR R0 ;R0 ← dimension number (0,2,4)
BWB2: MOV SOUGHT(R0),R1 ;R1 ← SOUGHT[DIMENSION]
MOV BWLOWS(RF),R2 ;
ADD R0,R2 ;
MOV (R2),R2 ;
ADD NEAREST,R2 ;R2 ← LOWBOUNDS[DIMENSION] + NEAREST
CMP R1,R2 ;
BLE BWB1 ;Can exit
MOV BWHIGHS(RF),R2 ;
ADD R0,R2 ;
MOV (R2),R2 ;
SUB NEAREST,R2 ;R2 ← HIGHBOUNDS[DIMENSION] - NEAREST
CMP R1,R2 ;
BGE BWB1 ;Can exit
TST (R0)+ ;
CMP R0,#4 ;
BLE BWB2 ;Repeat if necessary. Else, within bounds.
BWB3: MOV (SP)+,R2 ;Restore R2
TST R0 ;So caller won't have to
RTS RF ;Done
BWB1: CLR R0 ;Not within bounds. Ought to continue search.
BR BWB3 ;Done
; DISTANCE, DISLOOP, QUERY
COMMENT ⊗ Takes a pointer to a hunk in R0. Returns the distance from
that hunk to SOUGHT in R0. Actually, as soon as the distance is sure
to be greater than NEAREST, it just returns the current sum (which
will be an underestimate larger than NEAREST) ⊗
DISTANCE:
MOV R2,-(SP) ;Save R2
MOV R3,-(SP) ;Save R3
MOV R0,R2 ;
ADD #HLOW,R2 ;R2 ← LOC[HLOW];
MOV R0,R3 ;
ADD #HHIGH,R3 ;R3 ← LOC[HHIGH];
JSR PC,DISLOOP ;
MOV (SP)+,R3 ;Restore R3
MOV (SP)+,R2 ;Restore R2
RTS PC ;Done
DISLOOP:
COMMENT ⊗ R2 ← LOC[HLOW], R3 ← LOC[HHIGH]. Returns distance from
SOUGHT to these arrays in R0. Actually, as soon as the distance is
sure to be greater than NEAREST, it just returns the current sum
(which will be an underestimate larger than NEAREST) ⊗
MOV R4,-(SP) ;Save R4
CLR R0 ;R0 ← cumulative distance
CLR R4 ;R4 ← Dimension number (0,2,4)
DIS1: MOV R2,R1 ;
ADD R4,R1 ;
MOV (R1),R1 ;
SUB SOUGHT(R4),R1 ;R1 ← HLOW[DIMENSION] - SOUGHT[DIMENSION]
BGT DIS2 ;Below the left border?
MOV R3,R1 ;no.
ADD R4,R1 ;
MOV (R1),R1 ;
SUB SOUGHT(R4),R1 ;R1 ← SOUGHT[DIMENSION] - HHIGH[DIMENSION]
BLT DIS2 ;Above the right border?
CLR R1 ;No. Distance is 0.
DIS2: MUL R1,R1 ;R1 ← Distance squared
ADD R1,R0 ;
CMP R0,NEAREST ;Greater already than NEAREST?
BGT DIS4 ;yes
DIS3: TST (R4)+ ;no
CMP R4,#4 ;
BLE DIS1 ;Repeat for other dimensions
DIS4: MOV (SP)+,R4 ;Restore R4
RTS PC ;Done
ROUTINE QUERY,<QHUNK>
COMMENT ⊗ Takes a pointer to a bucket of hunks. Calls DISTANCE on
each entry in the bucket. ⊗
MOV QHUNK(RF),R0 ;
BEQ QUERY1 ;End of list?
MOV HNEXT(R0),QHUNK(RF) ;No
JSR PC,DISTANCE ;Get the distance.
CMP NEAREST,R0 ;Have we gotten closer?
BLE QUERY ;No. check the next in the bucket
MOV R0,NEAREST ;Yes. A new nearest.
BNE QUERY ;If not 0, go do it again.
QUERY1: RTS RF ;Done
; MAKETREE
BSIZE: 10 ;Number of hunks per bucket
ROUTINE MAKETREE,<MTLIST,MTLOW,MTHIGH>
COMMENT ⊗ Makes a tree out of the hunks in the MTLIST assuming that
they all lie in the bounds. Will put from 1 to BSIZE hunks in each
bucket. Returns the LOC[root node] in R0. Recursive. ⊗
;initialize local variables
DISC == -4 ; ie, can say DISC(RF)
DVAL == -6 ; ie, can say DVAL(RF)
LEFT == -10 ; ie, can say LEFT(RF)
RIGHT == -12 ; ie, can say RIGHT(RF)
CLR -(SP) ;DISC(RF) ← 0;
CLR -(SP) ;DVAL(RF) ← 0;
CLR -(SP) ;LEFT(RF) ← 0;
CLR -(SP) ;RIGHT(RF) ← 0;
MOV R2,-(SP) ;Save R2
MOV R3,-(SP) ;Save R3
MOV R4,-(SP) ;Save R4
MOV MTLIST(RF),R0 ;R0 ← List of hunks
BNE MT1 ;If any
JMP MT9 ;Do the return fixup, return R0 = 0.
MT1: ;see if we have less then BSIZ hunks.
MOV BSIZE,R1 ;R1 ← Count
MT12: MOV HNEXT(R0),R0 ;R0 ← next hunk
BEQ MT13 ;If any
SOB R1,MT12 ;
BR MT10 ;
MT13: CALL NWNODE,<R1,#-1,MTLIST(RF),R1> ;Put all hunks in bucket
JMP MT9 ;Do the return fixup
;Set DISC to direction of greatest spread;
MT10: CLR R4 ;R4 ← SPREAD ← 0
DEC DISC(RF) ;-1 is the initial discrim.
CLR R3 ;R3 ← Initialize the dimension (0,2,4)
MT3: MOV MTLOW(RF),R0 ;
ADD R3,R0 ;R0 ← LOWBOUNDS[DIMENSION]
MOV MTHIGH(RF),R1 ;
ADD R3,R1 ;R1 ← HIGHBOUNDS[DIMENSION]
CALL GETSPREAD,<MTLIST(RF),R3,(R0),(R1)>
CMP R0,R4 ;A wider spread?
BLE MT2 ;No
MOV R0,R4 ;
MOV R3,DISC(RF) ;
MT2: TST (R3)+ ;
CMP R3,#4 ;
BLE MT3 ;Repeat for each dimension
;take care of full region case
TST DISC(RF) ;Discrim = -1?
BGE MT4 ;No
CLR R0 ;
CALL NWNODE,<R0,DISC(RF),MTLIST(RF),R0> ;Yes.
JMP MT9 ;Do the return fixup
MT4: MOV MTLOW(RF),R0 ;
ADD DISC(RF),R0 ;R0 ← LOWBOUNDS[DISCRIM]
MOV MTHIGH(RF),R1 ;
ADD DISC(RF),R1 ;R1 ← HIGHBOUNDS[DISCRIM]
CALL GETDVAL,<MTLIST(RF),DISC(RF),(R0),(R1)>
MOV R0,DVAL(RF) ;
;Unzip the MTLIST into two chains.
JSR PC,NWHUNK
MOV R0,LEFT(RF) ;
MOV R0,R4 ;R4 is the PTRL
JSR PC,NWHUNK
MOV R0,RIGHT(RF) ;
MOV R0,R3 ;R3 is the PTRR
MOV MTLIST(RF),R2 ;R2 is the PTR
MT8: MOV R2,R1 ;
ADD #HHIGH,R1 ;
ADD DISC(RF),R1 ;
CMP (R1),DVAL(RF) ;HHIGH[PTR][DISCRIM] ≤ DVAL?
BGT MT5 ;No
MOV R2,HNEXT(R4) ;Yes. Put this hunk on the left chain.
MOV R2,R4 ;
BR MT7 ;
MT5: MOV R2,R1 ;
ADD #HLOW,R1 ;
ADD DISC(RF),R1 ;
CMP (R1),DVAL(RF) ;HLOW[PTR][DISCRIM] ≥ DVAL?
BLT MT6 ;No
MOV R2,HNEXT(R3) ;Yes. Put this hunk on the right chain.
MOV R2,R3 ;
BR MT7 ;
MT6: ;Must chop the hunk in two
JSR PC,NWHUNK ;Make a new left hunk
MOV R0,HNEXT(R4) ;Link it in
MOV R0,R4 ;
MOV R2,R1 ;Copy the bounds
ADD #HLOW,R1 ;
ADD #HLOW,R0 ;
MOV R3,-(SP) ;
MOV #6,R3 ;
MT11: MOV (R1)+,(R0)+ ;
SOB R3,MT11 ;
MOV (SP)+,R3 ;
MOV R4,R0 ;Put in new highbound(discrim) ← dval
ADD DISC(RF),R0 ;
MOV DVAL(RF),HHIGH(R0)
MOV R2,HNEXT(R3) ;Use the old hunk for the right. Link it in.
MOV R2,R3 ;
MOV R2,R0 ;Put in new lowbound(discrim) ← dval
ADD DISC(RF),R0 ;
MOV DVAL(RF),HLOW(R0)
MT7: MOV HNEXT(R2),R2 ;
BNE MT8 ;Repeat as necessary
CLR HNEXT(R4) ;Terminate new chains
CLR HNEXT(R3) ;
JSR PC,NWBOUNDS ;Recursive call on left chain
MOV R0,R2 ;Save R2 ← LOC[NEWBOUNDS]
MOV MTHIGH(RF),R1 ;
MOV (R1)+,(R0)+ ;Copy the highbounds
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV R2,R0 ;
ADD DISC(RF),R0 ;
MOV DVAL(RF),(R0) ; with HIGHBOUNDS[DISCRIM] ← DVAL
MOV LEFT(RF),R0 ;
CALL MAKETREE,<HNEXT(R0),MTLOW(RF),R2>
MOV R0,R3 ;R3 ← left subtree
MOV MTLOW(RF),R1 ;Recursive call on right chain
MOV R2,R0 ;
MOV (R1)+,(R0)+ ;Copy the lowbounds
MOV (R1)+,(R0)+ ;
MOV (R1),(R0) ;
MOV R2,R0 ;
ADD DISC(RF),R0 ;
MOV DVAL(RF),(R0) ; with LOWBOUNDS[DISCRIM] ← DVAL
MOV RIGHT(RF),R0 ;
CALL MAKETREE,<HNEXT(R0),R2,HHIGH(RF)>
CALL NWNODE,<DVAL(RF),DISC(RF),R3,R0>
MT9: MOV (SP)+,R4 ;Restore R4
MOV (SP)+,R3 ;Restore R3
MOV (SP)+,R2 ;Restore R2
ADD #10,SP ;Clear off local variables
RTS RF ;Return the full node in R0.
; GETSPREAD
ROUTINE GETSPREAD,<GTLIST,GTDIRECTION,GTLOW,GTHIGH>
COMMENT ⊗ Looks down the GTLIST of hunks, only examining the given
direction, and reports the greatest distance between the outlying
points. If there are only points at LOWB and HIGHB, the result is
given as 0 instead of HIGHB-LOWB. The answer is retured in R0. ⊗
MOV R2,-(SP) ;Save R2
MOV R3,-(SP) ;Save R3
MOV R4,-(SP) ;Save R4
MOV GTHIGH(RF),R2 ;Initialize the lowest we have seen
MOV GTLOW(RF),R3 ;Initialize the highest we have seen
MOV GTDIRECTION(RF),R0 ;
MOV GTLIST(RF),R4 ;R4 ← PTR ← head of the list
BEQ GTS1 ;if any
GTS4: MOV #HLOW,R1 ;
ADD GTDIRECTION(RF),R1
ADD R4,R1 ;
MOV (R1),R1 ;
MOV R1,R0 ;
SUB R2,R1 ;R1 ← HLOW[DIRECTION] - LOWEST
BGE GTS2 ;Not a new lowest
MOV R0,R2 ;A new lowest
GTS2: MOV #HHIGH,R1 ;
ADD GTDIRECTION(RF),R1
ADD R4,R1 ;
MOV (R1),R1 ;
MOV R1,R0 ;
SUB R3,R1 ;R1 ← HHIGH[DIRECTION] - HIGHEST
BLE GTS3 ;Not a new highest
MOV R0,R3 ;A new highest
GTS3: MOV HNEXT(R4),R4 ;Look at next hunk
BNE GTS4 ;If any
GTS1: MOV R3,R0 ;
SUB R2,R0 ;R0 ← HIGHEST - LOWEST
MOV GTHIGH(RF),R1 ;
SUB GTLOW(RF),R1 ;R1 ← GTHIGH - GLOW
CMP R0,R1 ;Is the spread the maximum?
BLT GTS5 ;No
CLR R0 ;Load up a zero
GTS5: MOV (SP)+,R4 ;Restore R4
MOV (SP)+,R3 ;Restore R3
MOV (SP)+,R2 ;Restore R2
RTS RF ;And return
; GETDVAL
CURHUNK:0 ;The current hunk that GETDVAL is sorting
HEAD: 0 ;Head of the list of sorted values
ROUTINE GETDVAL,<GDLIST,GDDIRECTION,GDLOW,GDHIGH>
COMMENT ⊗ Returns the value closest to the mean value of the list's
values in the given direction. This is returned in R0. ⊗
;initialize
MOV R2,-(SP) ;Save R2
MOV R3,-(SP) ;Save R3
MOV R4,-(SP) ;Save R4
MOV GDLOW(RF),R0 ;
JSR PC,NWSORT ;
MOV R0,R3 ;
MOV R0,HEAD ;HEAD ← R3 ← NWSORTCELL(LOW) (head of insertion list)
MOV GDHIGH(RF),R0 ;
JSR PC,NWSORT ;
MOV R0,SCNEXT(R3) ;SCNEXT[HEAD] ← NWSORTCELL(HIGH)
CLR SCNEXT(R0) ;Terminate the chain.
;sort the values by insertion sort in a list
MOV GDLIST(RF),CURHUNK ;CURHUNK ← Current hunk
BEQ GDV1 ;If any
GDV8: MOV HEAD,R3 ;R3 ← PTRB ← HEAD
MOV SCNEXT(R3),R4 ;R4 ← PTRF ← NEXT[PTRB]
MOV CURHUNK,R0 ;
ADD #HLOW,R0 ;
ADD GDDIRECTION(RF),R0
MOV (R0),R0 ;
MOV R0,R2 ;R2 ← VAL ← HLOW[CURHUNK][DIRECTION]
JSR PC,NWSORT ;R0 ← NWSORTCELL(VAL)
CMP R2,GDLOW(RF) ;If VAL ≠ LOWB
BEQ GDV2 ;
CMP R2,SCVAL(R4) ;find a place in sorted list
BLE GDV3 ;
GDV4: MOV R4,R3 ;
MOV SCNEXT(R4),R4 ;
CMP R2,SCVAL(R4) ;
BGT GDV4 ;
GDV3: MOV R4,SCNEXT(R0) ;the place is right between R3 and R4.
MOV R0,SCNEXT(R3) ;
MOV R0,R3 ;a new PTRB
GDV2: MOV CURHUNK,R0 ;
ADD #HHIGH,R0 ;
ADD GDDIRECTION(RF),R0
MOV (R0),R0 ;
MOV R0,R2 ;R2 ← VAL ← HHIGH[CURHUNK][DIRECTION]
JSR PC,NWSORT ;R0 ← NWSORTCELL(VAL)
CMP R2,GDHIGH(RF) ;If VAL ≠ HIGHB
BEQ GDV5 ;
CMP R2,SCVAL(R4) ;find a place in sorted list
BLE GDV6 ;
GDV7: MOV R4,R3 ;
MOV SCNEXT(R4),R4 ;
CMP R2,SCVAL(R4) ;
BGT GDV7 ;
GDV6: MOV R4,SCNEXT(R0) ;the place is right between R3 and R4.
MOV R0,SCNEXT(R3) ;
GDV5: MOV CURHUNK,R0 ;
MOV HNEXT(R0),CURHUNK ;Go to next hunk
BNE GDV8 ;If any
;select the mean value
GDV1: MOV GDHIGH(RF),R0 ;
SUB GDLOW(RF),R0 ;
ASR R0 ;R0 ← Mean value to aim for
MOV HEAD,R3 ;R3 ← PTRB ← HEAD
MOV SCNEXT(R3),R4 ;R4 ← PTRF ← NEXT[HEAD]
CMP SCVAL(R4),R0 ;Gone past yet?
BGE GDV12 ;Yes.
GDV9: MOV R4,R3 ;No. Move to next one.
MOV SCNEXT(R4),R4 ;
CMP SCVAL(R4),R0 ;Gone past yet?
BLT GDV9 ;No. try next one.
GDV12: CMP SCVAL(R4),GDHIGH(RF) ;Did we get to very end?
BNE GDV10 ;No.
MOV SCVAL(R3),R2 ;Yes. The answer will be VAL[PTRB]
BR GDV11 ;
GDV10: MOV SCVAL(R4),R2 ;The answer will be VAL[PTRF]
GDV11: MOV HEAD,R0 ;
JSR PC,RLSORT ;Get rid of all the sort cells
MOV R2,R0 ;R0 ← answer
MOV (SP)+,R4 ;Restore R4
MOV (SP)+,R3 ;Restore R3
MOV (SP)+,R2 ;Restore R2
RTS RF ;
; NWSORT, RLSORT, NWBOUNDS, NWHUNK, NWNODE
NWSORT:
COMMENT ⊗ Takes an item in R0 which is to be placed as the SCVAL of a
new sort cell. This cell is taken from large block space and is
pointed to by R0. ⊗
MOV R0,-(SP) ;Save the datum
MOV #SCSIZ,R0 ;
JSR PC,GTFREE ;R0 ← LOC[new sortcell]
MOV (SP)+,SCVAL(R0) ;Load up the SCVAL
RTS PC ;Done
RLSORT:
COMMENT ⊗ Takes a pointer to a sortcell in R0. It and all the cells
linked to it are returned to large block space. ⊗
TST R0 ;Check if we were given a real cell
BEQ RLS1 ;No.
RLS2: MOV SCNEXT(R0),-(SP);Save the next one for later.
JSR PC,RLFREE ;
MOV (SP)+,R0 ;Get the next on the list
BNE RLS2 ;If any, then repeat.
RLS1: RTS PC ;Done
NWHUNK: MOV #HUNKSZ,R0 ;
JSR PC,GTFREE ;
RTS PC ;
NWBOUNDS:
MOV #3,R0 ;
JSR PC,GTFREE ;
RTS PC ;
ROUTINE NWNODE,<NNDVAL,NNDDIS,NNDLEF,NNDRIG>
MOV #NODESZ,R0 ;
JSR PC,GTFREE ;R0 ← LOC[new node]
MOV NNDVAL(RF),TVAL(R0) ;Stuff the values in
MOV NNDDIS(RF),DISCRIM(R0) ;
MOV NNDLEF(RF),TLEFT(R0) ;
MOV NNDRIG(RF),TRIGHT(R0) ;
RTS RF ;Done
; Test
LOWS: .BLKW 3 ;Low universe bounds
HIGHS: .BLKW 3 ;High universe bounds
TREE: .BLKW 1 ;The tree in which we search
TEST: (Since that is what HAL likes to call it)
.MACRO MAKEHUNK XL,XH,YL,YH,ZL,ZH,NXT
JSR PC,NWHUNK ;R0 ← LOC[new hunk]
MOV R0,R1 ;
MOV XL,(R1)+ ;Stuff in the low bounds
MOV YL,(R1)+ ;Stuff in the low bounds
MOV ZL,(R1)+ ;Stuff in the low bounds
MOV XH,(R1)+ ;Stuff in the high bounds
MOV YH,(R1)+ ;Stuff in the high bounds
MOV ZH,(R1)+ ;Stuff in the high bounds
MOV NXT,(R1) ;Set the next pointer
.ENDM
MAKEHUNK #1,#2, #3,#4, #5,#6, #0
MOV R0,R2 ;R2 is the list of all hunks
MAKEHUNK #3,#4, #5,#6, #1,#2, R2
MOV R0,R2 ;
MAKEHUNK #5,#6, #5,#6, #1,#2, R2
MOV R0,R2 ;
MAKEHUNK #7,#10, #5,#6, #1,#2, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #1,#2, #1,#2, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #3,#4, #1,#2, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #5,#6, #7,#10, R2
MOV R0,R2 ;
MAKEHUNK #1,#2, #3,#4, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #5,#6, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #5,#6, #5,#6, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #7,#10, #5,#6, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #1,#2, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #3,#4, #3,#4, #3,#4, R2
MOV R0,R2 ;
MAKEHUNK #1,#7, #7,#8, #2,#5, R2
MOV R0,R2 ;
JSR PC,NWBOUNDS ;
MOV R0,LOWS ;LOWS ← R0 ← LOC[low bounds]
CLR (R0)+ ;Set all low bounds to 0
CLR (R0)+ ;
CLR (R0)+ ;
JSR PC,NWBOUNDS ;
MOV R0,HIGHS ;HIGHS ← R0 ← LOC[high bounds]
MOV #10,R4 ;
MOV R4,(R0)+ ;Set all high bounds to 10
MOV R4,(R0)+ ;
MOV R4,(R0)+ ;
CALL MAKETREE,<R2,LOWS,HIGHS>
MOV R0,TREE ;
MOV #12,R5 ;R5 ← Number of full tests (of =512 searches)
TSTA: MOV #10,R2 ;X
MOV R2,R3 ;Y
MOV R2,R4 ;Z
TSTX: MOV R2,SOUGHT ;
TSTY: MOV R3,SOUGHT+2 ;
TSTZ: MOV R4,SOUGHT+4 ;
MOV #200,NEAREST ;To initialize.
CALL NNSEARCH,<TREE,LOWS,HIGHS>
SOB R4,TSTZ ;
MOV #10,R4 ;
SOB R3,TSTY ;
MOV #10,R3 ;
SOB R2,TSTX ;
SOB R5,TSTA ;
BPT ;
; Known bugs
COMMENT ⊗
There is no call yet to BWB.
⊗